package orfeu.engine;


import java.util.Iterator;
import java.util.Vector;
import android.os.Vibrator;
import android.util.Log;
import android.content.Context;
import AI.*;

public class GameUpdater implements Runnable {
	// a list of objects that need to be updated
	public Vector<Sprite> updateList;

	// boolean for game state
	private boolean running;

	// FPS constants and time variables
	private static final int FPS = 30;
	private static final int SKIP_FRAMES = 1000 / FPS;
	private static final int MAX_FRAMESKIP = 5;
	private long nextGameTick;
	int loops;
	float interpolation;

	public GameUpdater() {
		updateList = new Vector<Sprite>();
		running = true;
	}

	public synchronized void updateElements()
	{
		Sprite aux;
		try{

			synchronized (updateList) {
				//checks to see if any elements have to be removed and removes them
				Iterator<Sprite> it = updateList.iterator();
				while(it.hasNext()) {
					aux = it.next();
					if(aux.remove()) it.remove();
				}

				
				//call the update function of the sprite
				for (int i = 0; i < updateList.size(); i++) {
					updateList.get(i).update(System.currentTimeMillis());
				}
				//waits until the other threads have finished their work on adding/removing sprites
				updateList.wait(10);
			}

		}
		catch(InterruptedException e){
			System.exit(0);
		}
	}

	public void run() {
		nextGameTick = System.currentTimeMillis();

		while (running) {
			loops = 0;
			while (System.currentTimeMillis() > nextGameTick && loops < MAX_FRAMESKIP) {
				// update objects
				updateElements();
				nextGameTick += SKIP_FRAMES;
				loops++;
			}

			//CHeck collisions. If hero dies a Death Exception will be sent
			try{
				this.checkCollision();
			}
			catch(DeathException e)
			{
				running = false;
				e.stopGame();
			}


			interpolation = (float)(System.currentTimeMillis() + SKIP_FRAMES - nextGameTick )/ (float)(SKIP_FRAMES);

			synchronized (updateList) {
				Iterator<Sprite> it = updateList.iterator();
				while(it.hasNext()){
					Sprite sp = it.next();
					sp.setInterpolation(interpolation);
				}
				updateList.notifyAll();
			}
		}

	}

	public void checkCollision() throws DeathException
	{
		
		Vector<Demon> demons = GLView.getGenerator().demons;
		Vector<Projectile> enemyprojectiles = GLView.getGenerator().myProjectiles;
		Vector<Projectile> myprojectiles = GLView.getGenerator().enemyProjectiles;
		Hero hero = Hero.getHero();

		GLView.getGenerator().detectProjectilesCollsion();//checks to see if 2 projectiles collide
		GLView.getGenerator().damageHero();//checks to see if any projectiles are hitting the hero
		GLView.getGenerator().damageDemons();//checks to see if any projectiles are hitting the demons

		//checks to see if any demons are intersecting the hero
		//if so, then destroy the demon and damage the hero
		synchronized (hero) {
			try{
				synchronized (demons) {
					try{
						Iterator<Demon> it = demons.iterator();
						while(it.hasNext())
						{
							Demon d = it.next();
							if(hero.collidesWith(d)){
								Hell.myaudioclip.play();
								((Vibrator)SpriteGameActivity.context.getSystemService(Context.VIBRATOR_SERVICE)).vibrate(30);
								hero.updateHealth(d.impactDamage);

								//Tell the sprite that is has to be removed
								d.setRemove();
								//Remove the sprite from the demon list
								it.remove();
								//Log.d("i","hero Health: " + hero.HEALTH);
								if(!hero.isAlive())
								{
									throw new DeathException();
								}
							}
						}
						demons.wait(50);

					}catch(InterruptedException e){
						System.exit(0);
					}
				}
				hero.wait(50);
			}catch(InterruptedException e){
				System.exit(0);
			}
		}
	}
	
	public void setRunning(boolean value) {
		this.running = value;
	}
}
